package com.loongtech.bi.synch;

import com.loongtech.bi.action.PageHelper;
import com.loongtech.bi.entity.system.EntityDaliyReport;
import com.loongtech.bi.entity.system.EntityMonitorConfig;
import com.loongtech.bi.entity.system.EntityMonitorResult;
import com.loongtech.bi.entity.system.EntityMonitorUserConfig;
import com.loongtech.bi.manager.flow.HadoopQueryManager;
import com.loongtech.bi.manager.system.*;
import com.loongtech.bi.support.AsyncHttpClientUtils;
import com.loongtech.core.util.Time;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.*;
import java.util.concurrent.ExecutionException;

import static com.loongtech.core.util.Time.getDateStr;

@Service
public class MonitorMailManager {
    @Resource
    private BiMonitorResultManager biMonitorResultManager;
    @Resource
    private BiMonitorConfigManager biMonitorConfigManager;
    @Resource
    private BiMonitorUserConfigManager biMonitorUserConfigManager;
    @Resource
    private DailyReportManager dailyReportManager;
    @Resource
    private HadoopQueryManager queryManager;
    @Resource
    private ConfigManager configManager;

    public void mail(String... mails) {
        String dateValue;
        boolean isTest = mails != null && mails.length > 0;
        if (isTest) {
            dateValue = mails[2];
        } else {
            dateValue = getDateStr(new Date(Time.currentTime() - Time.DAY)); //日期
        }

        /* 生成邮件内容，包括汇总和异常数据 */
        List<List<String>> slist = getSummary(dateValue);  // 取得监控汇总对象数据
        if (slist.size() <= 0) {  // 为空直接返回
            System.out.println("监控汇总对象数据为空!");
            return;
        }
        StringBuilder summary = generateSummaryTemp(slist);  // 转化对象数据为邮件内容

        List<List<String>> elist = getException(dateValue);  // 取得监控异常对象数据
        StringBuilder exceptions = generateExceptionTemp(elist);  // 转化对象数据为邮件内容

        StringBuilder emailContext = getEmailContext(summary, exceptions);  // 合并上述两份邮件内容


        /* 保存邮件内容到web服务器 */
        String mailName = dateValue + ".html";  // 邮件文件名
        String filepath = configManager.getConfigValueByName(ConfigManager.REPORT_EMAIL_ADDR) + "/" + mailName;  // 邮件在服务器上的路径
        saveHtml(filepath, emailContext.toString());  // 保存

        /* 发送报表链接到用户邮箱 */
        File t = new File(filepath);
        if (t.exists() && t.isFile()) {
            String mailurl = configManager.getConfigValueByName(ConfigManager.SELF_URL) + "/report/" + mailName;  // 邮件文件url
            sendMail(dateValue, mailurl, mails);
        } else {
            sendMail("linkmeliu@163.com", mailName + "没生成");
            sendMail("zhenghaiyuan@zulong.com", mailName + "没生成");
        }
    }

    private void sendMail(String dateValue, String mailurl, String... mails) {
        boolean isTest = mails != null && mails.length > 0;  // 是否就测试，是测试的话，只发mails中的邮件

        StringBuilder emailAddr = new StringBuilder();
        emailAddr.append("<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>" +
                "<html xmlns='http://www.w3.org/1999/xhtml'>" +
                "<head>" +
                "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />" +
                "<meta name='viewport' content='width=device-width, initial-scale=1.0'/>" +
                "</head>");
        emailAddr.append("<body><div align='center'>");
        emailAddr.append("<br/><br/><h2>各位好，");
        emailAddr.append(configManager.getConfigValueByName(ConfigManager.PROJECT_NAME));
        emailAddr.append("游戏产出汇总数据表如下，请点击链接查看：<br/><a href='");
        emailAddr.append(mailurl);
        emailAddr.append("'>");
        emailAddr.append(dateValue);
        emailAddr.append("日报表</a></h2>");
        emailAddr.append("</div>");
        emailAddr.append("</body></html>");

        if (isTest) {
            System.out.println("**********************邮件内容" + emailAddr.toString());
            for (String m : mails) {
                System.out.println("**********************给" + m + "发邮件");
                sendMail(m, emailAddr.toString());
            }
        } else {
            List<Integer> userIdList = biMonitorUserConfigManager.findByQuery("select userId from EntityMonitorUserGroup where groupId = ?", 100);
            if (null != userIdList && !userIdList.isEmpty()) {
                for (Integer userId : userIdList) {
                    EntityMonitorUserConfig entity = biMonitorUserConfigManager.getByQuery("from EntityMonitorUserConfig where id = ?", userId);
                    System.out.println("**********************给" + entity.getEmail() + "发邮件");
                    sendMail(entity.getEmail(), emailAddr.toString());
                }
            }
        }
    }

    private List<List<String>> getSummary(String dateValue) {
        ArrayList<List<String>> result = new ArrayList<>();
        List<EntityDaliyReport> list = dailyReportManager.findAll();

        if (null != list && list.size() != 0) {
            for (EntityDaliyReport entityDaliyReport : list) {
                if (entityDaliyReport.getDescription().contains("战斗力")) {
                    continue;
                }
                String sql1 = entityDaliyReport.getInquerySQLOne(dateValue);
//                System.out.println("@@@@@@@@@@@@@@@@@@111111111111111111111111111111111111111111111111111111111" + sql1 );
                String sql2 = entityDaliyReport.getInquerySQLTwo(dateValue);
//                System.out.println("@@@@@@@@@@@@@@@@@@22222222222222222222222222222222222222222222222222222222" + sql2 );
                System.out.println("***********" + entityDaliyReport.getId());
                Map.Entry<List<String>, List<Object[]>> ret = queryManager.executeSQL(sql1);
                Map.Entry<List<String>, List<Object[]>> ret2 = queryManager.executeSQL(sql2);

                Map<String, List<String>> tmp = new HashMap<>();  // serverid=ArrayList<String>
                if (null != ret && null != ret.getValue() && !ret.getValue().isEmpty()) {
                    for (int i = 0; i < ret.getValue().size(); i++) {
                        String serverId = ret.getValue().get(i)[0].toString();//服务器id
                        List<String> ll = tmp.get(serverId);
                        if (ll == null) {
                            ll = new ArrayList<>();
                            tmp.put(serverId, ll);
                        }


                        String outputName = entityDaliyReport.getDescription();
                        String serverName = BiPlatformManager.getServerNameById(serverId);
                        String maxValue = ret.getValue().get(i)[1].toString();//当服最大获取值
                        String avgValue = PageHelper.floatKeepTwoNumber(Double.parseDouble(ret.getValue().get(i)[2].toString())) + "";//当服平均获取值
                        String roleNum = ret.getValue().get(i)[3].toString();//服务器角色数
                        ll.add(dateValue);
                        ll.add(outputName);
                        ll.add(serverId);
                        ll.add(serverName);
                        ll.add(maxValue);
                        ll.add(avgValue);
                        ll.add(entityDaliyReport.getThreshHold().toString());
                        ll.add(roleNum);
                        ll.add("0");
                        ll.add("0");
                    }
                }

                if (null != ret2 && null != ret2.getValue() && !ret2.getValue().isEmpty()) {
                    for (int i = 0; i < ret2.getValue().size(); i++) {
                        String serverId = ret2.getValue().get(i)[0].toString();//服务器id
                        List<String> ll = tmp.get(serverId);
                        if (ll != null) {
                            String overRoleNum = ret2.getValue().get(i)[1].toString();//超出阈值角色数
                            Double percent = Double.parseDouble(overRoleNum) / Double.parseDouble(ll.get(7));

                            ll.set(8, overRoleNum);
                            ll.set(9, PageHelper.double2Percent(percent));
                        }
                    }
                }

                if (tmp.size() > 0) {
                    result.addAll(tmp.values());
                }
            }
        }

        return result;
    }

    private List<List<String>> getException(String dateValue) {
        ArrayList<List<String>> result = new ArrayList<>();

        List<EntityMonitorResult> exceptionList = biMonitorResultManager.findByQuery("from EntityMonitorResult where creatTime > ?", Time.getBeginningOfDay(Time.currentTime() - Time.DAY));
        if (null != exceptionList && exceptionList.size() > 0) {
            for (EntityMonitorResult entityMonitorResult : exceptionList) {
                ArrayList<String> arrayList = new ArrayList<>();
                EntityMonitorConfig config = biMonitorConfigManager.getByQuery("from EntityMonitorConfig where id = ?", entityMonitorResult.getJobId());
                if (config.getDescription().contains("战斗力")) {
                    continue;
                }
                String serverId = entityMonitorResult.getServerId();
                arrayList.add(dateValue);
                arrayList.add(config.getDescription());
                arrayList.add(serverId);
                arrayList.add(BiPlatformManager.getServerNameById(serverId));
                arrayList.add(entityMonitorResult.getUserOrGroupName());
                arrayList.add(entityMonitorResult.getResult());
                arrayList.add(config.getThreshHold().toString());
                result.add(arrayList);
            }
        }
        return result;
    }


    /**
     * Author: yuri
     * Description: 生成汇总表格
     * Date: 16:24 2016/11/7
     */
    private StringBuilder generateSummaryTemp(List<List<String>> list) {
        StringBuilder summaryTemp = new StringBuilder();
        if (null != list && list.size() != 0 && null != list.get(0) && list.get(0).size() != 0) {
            summaryTemp.append("<h3>汇总数据表</h3>");
            summaryTemp.append("<table align='center' border='1' cellpadding='0' cellspacing='0' width='90%' style='border-collapse: collapse;font-size:16px;'>");
            summaryTemp.append("<tr><th>日期</th><th>产出名称</th><th>服务器id</th><th>服务器名称</th><th>当服最大获取值</th><th>当服平均获取值</th><th>阈值</th><th>服务器角色数</th><th>超出阈值角色数</th><th>超过阈值角色数占比</th></tr>");
            for (List<String> aList : list) {
                summaryTemp.append("<tr>");
                for (int j = 0; j < list.get(0).size(); j++) {
                    Double a4 = Double.parseDouble(aList.get(4));
                    Double a6 = Double.parseDouble(aList.get(6));
                    String a9 = aList.get(9);

                    if ((j == 4 && (a4 > a6)) || (j == 9 && !"0.00%".equals(a9) && !"".equals(a9) && !"0".equals(a9))) {
                        summaryTemp.append("<td class='r'>");
                    } else if (j == 1) {
                        summaryTemp.append("<td class='l'>");
                    } else {
                        summaryTemp.append("<td>");
                    }
                    summaryTemp.append(aList.get(j));
                    summaryTemp.append("</td>");
                }
                summaryTemp.append("</tr>");
            }
            summaryTemp.append("</table>");
        }
        return summaryTemp;
    }

    /**
     * Author: yuri
     * Description: 生成异常表格
     * Date: 16:42 2016/11/7
     */
    private StringBuilder generateExceptionTemp(List<List<String>> list) {
        StringBuilder exceptionTemp = new StringBuilder();
        if (null != list && list.size() != 0 && null != list.get(0) && list.get(0).size() != 0) {
            exceptionTemp.append("<h3>异常数据表</h3>");
            exceptionTemp.append("<table align='center' border='1' cellpadding='0' cellspacing='0' width='90%' style='border-collapse: collapse;font-size:16px;'>");
            exceptionTemp.append("<tr><th>日期</th><th>产出说明</th><th>服务器id</th><th>服务器名称</th><th>roleid</th><th>角色获取总值</th><th>阈值</th></tr>");
            for (List<String> aList : list) {
                exceptionTemp.append("<tr>");
                for (int j = 0; j < list.get(0).size(); j++) {
                    if (1 == j || 4 == j) {
                        exceptionTemp.append("<td class='l'>");
                    } else if (5 == j) {
                        exceptionTemp.append("<td class='r'>");
                    } else {
                        exceptionTemp.append("<td>");
                    }

                    if (5 == j) {
                        if (aList.get(j) != null && aList.get(j).contains(".")) {
                            exceptionTemp.append(aList.get(j).split("\\.")[0]);
                        } else {
                            exceptionTemp.append(aList.get(j));
                        }
                    } else {
                        exceptionTemp.append(aList.get(j));
                    }

                    exceptionTemp.append("</td>");
                }
                exceptionTemp.append("</tr>");
            }
            exceptionTemp.append("</table>");
        }
        return exceptionTemp;
    }

    /**
     * Author: yuri
     * Description:生成邮件内容
     * Date: 16:44 2016/11/7
     */
    private StringBuilder getEmailContext(StringBuilder summary, StringBuilder exceptions) {
        StringBuilder emailContents = new StringBuilder();
        emailContents.append("<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>" +
                "<html xmlns='http://www.w3.org/1999/xhtml'>" +
                "<head>" +
                "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />" +
                "<style type='text/css'>" +
                "td {text-align: center;width:8%;} .r{color:red;} .l{width:20%;}</style>" +
                "<title>HTML Email</title>" +
                "<meta name='viewport' content='width=device-width, initial-scale=1.0'/>" +
                "</head>");
        emailContents.append("<body><div align='center'>");
        emailContents.append(summary);
        emailContents.append("<br/>");
        emailContents.append(exceptions);
        emailContents.append("</div>");
        emailContents.append("</body></html>");
        return emailContents;
    }

    /**
     * Author: yuri
     * Description:发送邮件
     * <p>
     * Date: 16:44 2016/11/7
     */
    private void sendMail(String email, String context) {
        Map<String, Object> params = new HashMap<>();
        String url = configManager.getConfigValueByName(ConfigManager.ALARM_HOST) + "/mail";
        params.put("subject", configManager.getConfigValueByName(ConfigManager.PROJECT_NAME) + "游戏产出异常告警！");
        params.put("receivers", email);
        params.put("content", context);
        params.put("gameId", "209");
        params.put("ccs", "zulongops@zulong.com");
        try {
            AsyncHttpClientUtils.asyncSendHttpPostRequest(url, params);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    /**
     * Author: yuri
     * Description: 上传报表内容到服务器
     * Date: 16:04 2016/11/9
     */
    private static void saveHtml(String filepath, String str) {
        boolean flag = false;
        try {
            File file = new File(filepath);
            // 路径为文件且不为空则进行删除
            if (file.isFile() && file.exists()) {
                flag = file.delete();
            }
            if (!flag) {
                System.out.println("**********旧报表不存在，删除失败！");
            }
            OutputStreamWriter outs = new OutputStreamWriter(new FileOutputStream(filepath, false), "utf-8");
            outs.write(str);
            outs.close();
        } catch (IOException e) {
            System.out.println("*************保存Html文件出错！");
            e.printStackTrace();
        }
    }
}
